package com.tian.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.tian.config.RedisConfig;
import com.tian.dto.MessageTemplateDto;
import com.tian.dto.SendCodeReqDto;
import com.tian.enums.MessageTemplateTypeEnums;
import com.tian.enums.ResultCode;
import com.tian.feign.MessageTemplateFeignClient;
import com.tian.mq.PhoneMessageProducer;
import com.tian.service.SendCodeService;
import com.tian.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author tianwc  公众号：java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年05月11日 16:49
 * 博客地址：<a href="http://woaijava.cc/">博客地址</a>
 */
@Slf4j
@Service
@Scope(scopeName = "prototype")
public class SendCodeServiceImpl implements SendCodeService {
    @Resource
    private RedisConfig redisConfig;
    @Resource
    private MessageTemplateFeignClient messageTemplateFeignClient;
    @Resource
    private LimiterUtil limiterUtil;
    @Resource
    private PhoneMessageProducer phoneMessageProducer;

    @Override
    public CommonResult<Boolean> sendCode(String phone, String codeCachePre, Integer msgType) {
        if (StringUtil.isEmpty(phone)) {
            return CommonResult.failed(ResultCode.VALIDATE_FAILED);
        }
        ParamValidate.isNull(phone, "phone参数为空");
        //同一个手机号码 发送次数限流
        //同一个手机号每秒 最多只能发5次
        boolean limit = limiterUtil.slidingWindow(RedisConstantPre.MESSAGE_LIMIT_KEY_PRE + phone, (new Date()).getTime(), 60000L, 5);
        if (limit) {
            return CommonResult.failed(ResultCode.SEND_MESSAGE_LIMIT);
        }
        CommonResult<MessageTemplateDto> commonResult = messageTemplateFeignClient.queryByMessageType(msgType);
        if (commonResult.getCode() != ResultCode.SUCCESS.getCode()) {
            log.error("短信模板不存在，tye={}", msgType);
            return CommonResult.failed(ResultCode.VALIDATE_FAILED);
        }
        MessageTemplateDto messageTemplateDto = commonResult.getData();
        //生成随机验证码
        String code = RandomUtil.randomNumbers(6);
        log.info("登录发送验证码：{}", code);
        //发送验证码
        String content = messageTemplateDto.getContent();
        //验证码占位符
        String newContent = content.replace(messageTemplateDto.getContentParam(), code);
        //调用MQ  异步发送短信验证码
        phoneMessageProducer.sendPhoneMessage(phone, newContent);
        //存到redis中 设置有效期 60秒
        //60秒后需要重现发送
        redisConfig.set(codeCachePre + phone, code, 60);
        return CommonResult.success(Boolean.TRUE);
    }

    @Override
    public CommonResult<Boolean> codeValid(String phone, String code, String codeCachePre) {
        if (StringUtil.isEmpty(phone) || StringUtil.isEmpty(code)) {
            return CommonResult.failed(ResultCode.VALIDATE_FAILED);
        }
        String key = codeCachePre + phone;
        Object codeCache = redisConfig.get(key);
        if (codeCache == null) {
            return CommonResult.failed(ResultCode.VALIDATE_FAILED);
        }
        if (!code.equals(codeCache.toString())) {
            boolean limit = limiterUtil.slidingWindow(key, (new Date()).getTime(), 60000L, 5);
            if (limit) {
                return CommonResult.failed(ResultCode.SEND_MESSAGE_LIMIT);
            }
        }
        return CommonResult.success(Boolean.TRUE);
    }
}

